#include "serializer/traits.h"

#include <gtest/gtest.h>

#include <array>
#include <deque>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace serializer;

/**
 * 测试序列容器检测
 */
TEST(ContainerTraitsTest, sequence_container_detection)
{
    // 标准序列容器
    static_assert(SequenceContainer<std::vector<int>>);
    static_assert(SequenceContainer<std::list<int>>);
    static_assert(SequenceContainer<std::deque<int>>);
    // std::array 没有 push_back 或 insert，所以不满足 SequenceContainer
    // static_assert(SequenceContainer<std::array<int, 5>>);
    static_assert(SequenceContainer<std::string>);

    // 非序列容器
    static_assert(!SequenceContainer<std::set<int>>);
    static_assert(!SequenceContainer<std::map<int, int>>);
    static_assert(!SequenceContainer<std::unordered_set<int>>);
    static_assert(!SequenceContainer<std::unordered_map<int, int>>);
    static_assert(!SequenceContainer<std::stack<int>>);
    static_assert(!SequenceContainer<std::queue<int>>);
    static_assert(!SequenceContainer<std::priority_queue<int>>);

    // 非容器类型
    static_assert(!SequenceContainer<int>);
    static_assert(!SequenceContainer<double>);
}

/**
 * 测试关联容器检测
 */
TEST(ContainerTraitsTest, associative_container_detection)
{
    // 标准关联容器
    static_assert(AssociativeContainer<std::set<int>>);
    static_assert(AssociativeContainer<std::map<int, std::string>>);
    static_assert(AssociativeContainer<std::unordered_set<int>>);
    static_assert(AssociativeContainer<std::unordered_map<int, std::string>>);

    // 序列容器不应该被识别为关联容器
    static_assert(!AssociativeContainer<std::vector<int>>);
    static_assert(!AssociativeContainer<std::list<int>>);
    static_assert(!AssociativeContainer<std::deque<int>>);
    static_assert(!AssociativeContainer<std::array<int, 5>>);

    // 基础类型不应该被识别为关联容器
    static_assert(!AssociativeContainer<int>);
    static_assert(!AssociativeContainer<std::string>);
}

/**
 * 测试适配器容器检测
 */
TEST(ContainerTraitsTest, adapter_container_detection)
{
    // 标准适配器容器
    static_assert(AdapterContainer<std::stack<int>>);
    static_assert(AdapterContainer<std::queue<int>>);
    static_assert(AdapterContainer<std::priority_queue<int>>);

    // 自定义底层容器的适配器也应该被识别
    static_assert(AdapterContainer<std::stack<int, std::vector<int>>>);
    static_assert(AdapterContainer<std::queue<int, std::list<int>>>);
    static_assert(AdapterContainer<std::priority_queue<int, std::vector<int>>>);

    // 非适配器容器不应该被识别
    static_assert(!AdapterContainer<std::vector<int>>);
    static_assert(!AdapterContainer<std::set<int>>);
    static_assert(!AdapterContainer<std::map<int, int>>);

    // 基础类型不应该被识别为适配器容器
    static_assert(!AdapterContainer<int>);
    static_assert(!AdapterContainer<std::string>);
}

/**
 * 测试基础容器概念
 */
TEST(ContainerTraitsTest, basic_container_detection)
{
    // 所有标准容器都应该满足基础容器概念
    static_assert(BasicContainer<std::vector<int>>);
    static_assert(BasicContainer<std::list<int>>);
    static_assert(BasicContainer<std::deque<int>>);
    static_assert(BasicContainer<std::array<int, 5>>);
    static_assert(BasicContainer<std::set<int>>);
    static_assert(BasicContainer<std::map<int, int>>);
    static_assert(BasicContainer<std::string>);

    // 适配器容器不满足基础容器概念（没有迭代器）
    static_assert(!BasicContainer<std::stack<int>>);
    static_assert(!BasicContainer<std::queue<int>>);
    static_assert(!BasicContainer<std::priority_queue<int>>);

    // 基础类型不满足基础容器概念
    static_assert(!BasicContainer<int>);
    static_assert(!BasicContainer<double>);
}

/**
 * 测试连续序列容器检测
 */
TEST(ContainerTraitsTest, contiguous_sequence_container_detection)
{
    // 连续内存容器
    static_assert(ContiguousSequenceContainer<std::vector<int>>);
    // std::array 不满足 SequenceContainer，所以也不满足 ContiguousSequenceContainer
    // static_assert(ContiguousSequenceContainer<std::array<int, 5>>);
    static_assert(ContiguousSequenceContainer<std::string>);

    // 非连续内存容器
    static_assert(!ContiguousSequenceContainer<std::list<int>>);
    static_assert(!ContiguousSequenceContainer<std::deque<int>>);

    // 关联容器不是连续序列容器
    static_assert(!ContiguousSequenceContainer<std::set<int>>);
    static_assert(!ContiguousSequenceContainer<std::map<int, int>>);
}

/**
 * 测试映射容器和集合容器检测
 */
TEST(ContainerTraitsTest, map_and_set_container_detection)
{
    // 映射容器
    static_assert(MapContainer<std::map<int, std::string>>);
    static_assert(MapContainer<std::unordered_map<int, std::string>>);

    // 集合容器
    static_assert(SetContainer<std::set<int>>);
    static_assert(SetContainer<std::unordered_set<int>>);

    // 序列容器既不是映射也不是集合
    static_assert(!MapContainer<std::vector<int>>);
    static_assert(!SetContainer<std::vector<int>>);
    static_assert(!MapContainer<std::list<int>>);
    static_assert(!SetContainer<std::list<int>>);
}

/**
 * 测试具体适配器类型检测
 */
TEST(ContainerTraitsTest, specific_adapter_detection)
{
    // 栈适配器
    static_assert(StackAdapter<std::stack<int>>);
    static_assert(!StackAdapter<std::queue<int>>);
    // priority_queue 也满足 StackAdapter 的要求（有 push、top、pop）
    static_assert(StackAdapter<std::priority_queue<int>>);

    // 队列适配器
    static_assert(QueueAdapter<std::queue<int>>);
    static_assert(!QueueAdapter<std::stack<int>>);
    static_assert(!QueueAdapter<std::priority_queue<int>>);

    // 优先队列适配器
    static_assert(PriorityQueueAdapter<std::priority_queue<int>>);
    static_assert(!PriorityQueueAdapter<std::stack<int>>);
    static_assert(!PriorityQueueAdapter<std::queue<int>>);
}

/**
 * 测试能力检测概念
 */
TEST(ContainerTraitsTest, capability_detection)
{
    // 迭代器能力
    static_assert(HasIterators<std::vector<int>>::value);
    static_assert(HasIterators<std::set<int>>::value);
    static_assert(!HasIterators<std::stack<int>>::value);
    static_assert(!HasIterators<int>::value);

    // 大小查询能力
    static_assert(HasSize<std::vector<int>>::value);
    static_assert(HasSize<std::stack<int>>::value);
    static_assert(!HasSize<int>::value);

    // 空状态查询能力
    static_assert(HasEmpty<std::vector<int>>::value);
    static_assert(HasEmpty<std::stack<int>>::value);
    static_assert(!HasEmpty<int>::value);

    // 连续内存能力
    static_assert(HasContiguousMemory<std::vector<int>>::value);
    static_assert(HasContiguousMemory<std::array<int, 5>>::value);
    static_assert(!HasContiguousMemory<std::list<int>>::value);

    // 随机访问能力
    static_assert(HasRandomAccess<std::vector<int>>::value);
    static_assert(HasRandomAccess<std::deque<int>>::value);
    static_assert(!HasRandomAccess<std::list<int>>::value);

    // 插入能力
    static_assert(HasInsert<std::vector<int>>::value);
    static_assert(HasInsert<std::set<int>>::value);
    static_assert(!HasInsert<std::array<int, 5>>::value);

    // push_back 能力
    static_assert(HasPushBack<std::vector<int>>::value);
    static_assert(HasPushBack<std::list<int>>::value);
    static_assert(!HasPushBack<std::set<int>>::value);
    static_assert(!HasPushBack<std::array<int, 5>>::value);

    // 预留能力
    static_assert(HasReserve<std::vector<int>>::value);
    static_assert(!HasReserve<std::list<int>>::value);
    static_assert(!HasReserve<std::array<int, 5>>::value);
}

/**
 * 测试类型特征检测
 */
TEST(ContainerTraitsTest, type_trait_detection)
{
    // 键类型检测
    static_assert(HasKeyType<std::set<int>>::value);
    static_assert(HasKeyType<std::map<int, std::string>>::value);
    static_assert(!HasKeyType<std::vector<int>>::value);

    // 映射类型检测
    static_assert(HasMappedType<std::map<int, std::string>>::value);
    static_assert(!HasMappedType<std::set<int>>::value);
    static_assert(!HasMappedType<std::vector<int>>::value);

    // 键值访问检测
    static_assert(HasKeyValueAccess<std::map<int, std::string>>::value);
    static_assert(!HasKeyValueAccess<std::set<int>>::value);
    static_assert(!HasKeyValueAccess<std::vector<int>>::value);

    // 容器类型检测（适配器）
    static_assert(HasContainerType<std::stack<int>>::value);
    static_assert(HasContainerType<std::queue<int>>::value);
    static_assert(!HasContainerType<std::vector<int>>::value);
}

/**
 * 测试运行时容器验证
 */
TEST(ContainerTraitsTest, runtime_container_verification)
{
    std::vector<int> vec{1, 2, 3, 4, 5};
    std::set<int> s{1, 2, 3, 4, 5};
    std::array<int, 5> arr{1, 2, 3, 4, 5};
    std::stack<int> stack;

    // 这些容器应该具有预期的特征
    EXPECT_TRUE((SequenceContainer<decltype(vec)>));
    EXPECT_TRUE((BasicContainer<decltype(vec)>));
    EXPECT_TRUE((ContiguousSequenceContainer<decltype(vec)>));

    EXPECT_TRUE((AssociativeContainer<decltype(s)>));
    EXPECT_TRUE((BasicContainer<decltype(s)>));
    EXPECT_TRUE((SetContainer<decltype(s)>));

    EXPECT_TRUE((SequenceContainer<decltype(arr)>));
    EXPECT_TRUE((BasicContainer<decltype(arr)>));
    EXPECT_TRUE((ContiguousSequenceContainer<decltype(arr)>));

    EXPECT_TRUE((AdapterContainer<decltype(stack)>));
    EXPECT_TRUE((StackAdapter<decltype(stack)>));
    EXPECT_FALSE((BasicContainer<decltype(stack)>));

    // 验证运行时行为
    EXPECT_EQ(vec.size(), 5);
    EXPECT_EQ(s.size(), 5);
    EXPECT_EQ(arr.size(), 5);
    EXPECT_EQ(stack.size(), 0);
}

/**
 * 测试边缘情况和错误处理
 */
TEST(ContainerTraitsTest, edge_cases_and_error_handling)
{
    // 测试空类型
    struct EmptyType
    {
    };

    static_assert(!SequenceContainer<EmptyType>);
    static_assert(!AssociativeContainer<EmptyType>);
    static_assert(!AdapterContainer<EmptyType>);
    static_assert(!BasicContainer<EmptyType>);

    // 测试指针类型
    static_assert(!SequenceContainer<int *>);
    static_assert(!AssociativeContainer<int *>);
    static_assert(!AdapterContainer<int *>);

    // 测试引用类型
    static_assert(!SequenceContainer<std::vector<int> &>);
    static_assert(!AssociativeContainer<std::set<int> &>);

    // 测试 const 类型
    // const 容器无法满足需要修改操作的概念
    static_assert(!SequenceContainer<const std::vector<int>>);
    // AssociativeContainer 不需要修改操作，只需要类型特征
    static_assert(AssociativeContainer<const std::set<int>>);
    static_assert(BasicContainer<const std::array<int, 5>>);
}